from pylons import config

from creoleparser.dialects import Creole10
from creoleparser.core import Parser, preprocess, fragmentize

from mtp.lib import helpers as h

import genshi.builder as bldr
from lxml import etree

import logging
log = logging.getLogger(__name__)

def macro_func(name, arg, body):
    # turn macro's into xml elements that can be processed later
    return bldr.tag.macro(body, name=name, arg=arg)

def path_func(name):
    return h.url_for('page', id=name.replace(' ', '_'))

mtp_dialect=Creole10(
    wiki_links_base_url='',
    interwiki_links_base_urls={'wikicreole':'http://wikicreole.org/wiki/'},
    macro_func=macro_func, 
    wiki_links_path_func=path_func,
    use_additions=True,
)

class MTPParser(Parser):
    def generate(self, text, element_store=None):
        if element_store is None:
            element_store = {}
        text = preprocess(text,self.dialect)
        stream = bldr.tag.div(fragmentize(text,self.dialect.parse_order,element_store)).generate()
        return stream

CreoleParser = MTPParser(dialect=mtp_dialect, method="xml")


def apply_macros(xml):
    macros = xml.xpath('//macro')
    for macro in macros:
        name = macro.get('name')
        arg = macro.get('arg')
        try:
            macrofunc = config['mtp.macros'][name]
        except KeyError:
            log.warn('no such macro %s' % name)
            ret = None
        else:
            ret = macrofunc(arg, macro) 

        parent = macro.getparent()

        if ret is None:
            parent.remove(macro)
        elif isinstance(ret, etree._Element):
            parent.replace(macro, ret)
        else:
            span = etree.Element('span')
            span.text = str(ret)
            parent.replace(macro, span)


def apply_plugins(xml):
    for func in config['mtp.plugin_wikimodifiers']:
        func(xml)


def mtpparse(text):
    """ main wiki rendering function. passes text first thru creole to produce xml,
    then parses the result as xml for further processing """

    stream = CreoleParser(text)
    xml = etree.fromstring(stream)
    apply_macros(xml)
    apply_plugins(xml)

    return etree.tostring(xml)


